/**
 * Created by liuchuanyang on 2017/8/4.
 */

import _ from 'lodash';
import { $utils, $pageUtils } from '@jzl/utils'
import PageItemCommonStyle from '@jzl/utils/common/pi-common-style.js';
import TPL_NODES from "./tpl-nodes";
import TPL_CATES from "./tpl-cate";
import {DFT_ICONS} from "@jzl/icons";

const _LOW = {sType: '', show: null, sFormula: '', aType: '', active: null, aFormula: ''}; // aType: 'formula'
const _RESP = {
  type: 'resp',  // resp-普通响应式 c24, c5 c7 c9, c10
  xsc: -1, xso: 0, xss: null,
  smc: -1, smo: 0, sms: null,
  mdc: -1, mdo: 0, mds: null,
  lgc: -1, lgo: 0, lgs: null,
  xlc: -1, xlo: 0, xls: null,
  xxlc: -1, xxlo: 0, xxls: null
};
const _ANIME = {
  enable: false,
  play: 'view',   // auto | view
  duration: 500,
  delay: 0,
  easing: 'linear',
  direction: 'normal', // normal | reverse
  loop: 1,
  stagger: false
};

export const isTypeEle = (style, type) => {
  let nodeType = _.get(style, '_component', '') || _.get(style, "_node");
  let types = (nodeType || "").split(',');

  if (_.indexOf(types, type) >= 0) {
    return true;
  }

  return false;
}

export const _getAlias = (code, items) => {   // 得到别名，如果有重复，重复生成
  let repeat = false;
  let alias;

  if (code) {
    alias = code.substr(0, 3);
  } else {
    alias = $utils.getNanoid(4, 'CHAR');
  }

  if (items?.length) {
    for (let i = 0; i < items.length; i++) {

      let it = items[i];
      if (_.get(it, 'alias') === alias) {
        repeat = true;
        break;
      }
    }
  }

  if (!repeat) {
    return alias;
  } else {
    return _getAlias(null, items);
  }
}

export const _dragClone = (def, items = null) => {
  let item = $pageUtils.getItemByDef(def);
  item.alias = _getAlias(item.code, items);
  item.subs = [];

  return item;
}

export const clearDefaultStyle = (istyle) => {

  if (!istyle) return null;

  let style = _.cloneDeep(istyle);

  for (let prop in style) {
    if (['_common_style', '_ss', '_sh'].indexOf(prop) >= 0) {
      style[prop] = $pageUtils.clearDefaultStyleUnit(style[prop]);
    } else if ('_low' === prop) {
      style[prop] = clearDefaultLowUnit(style[prop]);
    } else if ('_resp' === prop) {
      style[prop] = clearDefaultRespUnit(style[prop]);
    } else if ('_anime' === prop) {
      style[prop] = clearDefaultAnimeUnit(style[prop]);
    } else if (_.startsWith(prop, "_")) {
      continue;
    } else if (_.isObject(style[prop])) {
      style[prop] = clearDefaultStyle(style[prop]);
    }
  }

  return style;
}

// pageUtils.clearDefaultStyleUnit 代替
/*
export const clearDefaultStyleUnit = (istyle) => {

  let style = _.omitBy(istyle, (val, key) => {
    if ((_.isNumber(val) || _.isString(val)) && val === PageItemCommonStyle[key]) {
      return true;
    } else if (_.isObject(val)) {
      _.omitBy(val, (v, k) => {
        if ((_.isNumber(v) || _.isString(v)) && v === _.get(PageItemCommonStyle, `${key}.${k}`)) {
          delete val[k];
        }
      });
    }
    return false;
  })

  return style;
}*/

export const clearDefaultLowUnit = (lowInfo) => {
  return clearDefaultUnit(lowInfo, _LOW);
}
export const clearDefaultRespUnit = (lowInfo) => {
  return clearDefaultUnit(lowInfo, _RESP);
}
export const clearDefaultAnimeUnit = (lowInfo) => {
  return clearDefaultUnit(lowInfo, _ANIME);
}

export const clearDefaultUnit = (obj, baseObj) => {
  let pureObj = _.omitBy(obj, (val, key) => {
    if ((_.isNumber(val) || _.isString(val) || _.isBoolean(val)) && val === baseObj[key]) {
      return true;
    }
    return false;
  })

  return pureObj;
}

export const getNodeType = (data) => {
  return $pageUtils.getPageNodeType(data)
}

export const getNodeTypeIcon = (data, isRoot = false) => {
  return $pageUtils.getPageNodeTypeIcon(data, isRoot)
}

export const getNodeTypeLabel = (data, isRoot) => {

  let nodeType = _.get(data, "_node");
  let multiple = _.get(data, "_multiple");    // 兼容以前

  if (isRoot) {
    return `组件【${_.get(data, "_name") || _.get(data, "component")}】`;
  } else if (nodeType === 'img') {
    return "元素【图片】";
  } else if (nodeType === 'text') {
    return "元素【文字】";
  } else if (nodeType === 'icon') {
    return "元素【图标】";
  } else if (nodeType === 'grid' || multiple === 'grid') {
    return "元素【多列】";
  } else if (nodeType === 'slider' || multiple === 'slider') {
    return "元素【轮播】";
  } else if (nodeType === 'list' || multiple === 'list' || multiple) {
    return "元素【列表】";
  }

  return "元素";
}

export const isMultipleNode = (nodeDef) => {
  let nodeType = _.get(nodeDef, "_type") || _.get(nodeDef, "_node");;
  return _.indexOf(['slider', 'list', 'grid', 'tabs', 'collapse', 'JzlList'], nodeType) >= 0 || _.get(nodeDef, "_multiple");
}

export const isDataNode = (nodeDef) => {
  let nodeType = _.get(nodeDef, '_type') || _.get(nodeDef, "_node");;
  let isMultiple = _.get(nodeDef, '_multiple');

  return isModelNode(nodeDef) || _.indexOf(['text', 'icon', 'img', 'image', 'video', 'slider', 'list', 'grid', 'tabs', 'collapse'], nodeType) >= 0 || isMultiple;
}

export const isModelNode = (nodeDef) => {
  /*let nodeType = _.get(nodeDef, '_node');
  // let isActionComp = _.findIndex(TPL_CATES.actionELems, ele => ele.component === nodeType) >= 0;
  let isFormComp = _.findIndex(TPL_CATES.formElems, ele => ele.component === nodeType) >= 0;

  return /!*isActionComp || *!/isFormComp || _.indexOf(['sliderComp', 'collapseComp', 'tabsComp', 'cascaderComp', 'paginationComp'], nodeType) >= 0;*/

  return !_.isEmpty(nodeDef?._mo)
}

export const isLeafNode = (nodeDef) => {
  let nodeType = _.get(nodeDef, "_type") || _.get(nodeDef, "_node"); //  || _.get(nodeDef, "_component");
  return _.indexOf(['text', 'icon', 'img', 'video'], nodeType) >= 0;
}

export const isMicroComp = (nodeDef) => {
  let nodeType = _.get(nodeDef, '_type') || _.get(nodeDef, '_node');
  let nodeRole = _.get(nodeDef, '_node');
  let compLib = _.get(nodeDef, '_lib');
  let isComp = false;
  let simples = ['div', 'text', 'icon', 'img', 'video']
  let roles = [ 'c$boxComp' ]

  if (_.findIndex(simples, type => type === nodeType) >= 0) return false;
  if(_.findIndex(roles, role => role === nodeRole) >= 0) return false;
  if (!!compLib) return true;
  for (let cate in TPL_CATES) {
    isComp = _.findIndex(TPL_CATES[cate], ele => ele.component === nodeRole) >= 0;

    if (isComp) break;
  }

  return isComp;
}

export const getItemRootByNode = (node) => {
  if (!node) return null;
  let isRoot = _.get(node, "data.isRoot");
  if (isRoot) return node; // _.get(node, "data.code");

  let parent = _.get(node, "parent");
  return getItemRootByNode(parent);
}

export const resetCode = (def) => {
  if (!def) return null;

  def._code = $utils.getNanoid(10);

  for (let prop in def) {
    if (!_.startsWith(prop, "_")) {
      resetCode(def[prop]);
    }
  }
}

export const getLowPlain = () => {
  return _.cloneDeep(_LOW);
}

export const getRespPlain = () => {
  return _.cloneDeep(_RESP);
}

export const getAnimePlain = () => {
  return _.cloneDeep(_ANIME);
}

// 复制组件定义
export const getNodeCompTpl = (nodeComp) => {
  return _.cloneDeep(_.get(TPL_NODES, `${nodeComp}.def`));
}

export const getPropName = (prop, allVars, idx = 0) => {
  if (_.findIndex(allVars, {prop}) < 0) return prop;

  idx++;
  let newProp = `${prop}${idx}`;
  return getPropName(newProp, allVars, idx);
}

export const changeValName = (def, map) => {
  if (!def) return;

  for (let prop in map) {
    if (def._value === prop) {
      def._value = map[prop];
    }

    if (def._ext) {
      let prefix = `${prop}.`;
      let isPrefix = _.startsWith(def._ext.optionsDef, prefix);
      if (def._ext.optionsDef === prop || isPrefix) {
        if (isPrefix) {
          def._ext.optionsDef = _.replace(new RegExp(`^${ prop }`), map[prop]);
        } else {
          def._ext.optionsDef = map[prop];
        }
      }

      let isTotalPrefix = _.startsWith(def._ext.optionsDef, prefix);
      if (def._ext.totalDef === prop || isTotalPrefix) {
        if (isTotalPrefix) {
          def._ext.totalDef = _.replace(new RegExp(`^${ prop }`), map[prop]);
        } else {
          def._ext.totalDef = map[prop];
        }
      }
    }
  }
  for (let prop in def) {
    if (_.startsWith(prop, "_")) {
      // continue;
    } else if (_.isObject(def[prop])) {
      changeValName(def[prop], map);
    }
  }
}

// 复制组件定义和变量修改
export const getNodeCompDefInfo = (nodeComp, item) => {
  let nodeInfo = _.cloneDeep(nodeComp);

  if (_.isString(nodeComp)) {  // 基础组件，按照名称
    nodeInfo = _.cloneDeep(_.get(TPL_NODES, `${nodeComp}`));
  }
  if (!nodeInfo || !_.isObject(nodeInfo)) return;
  let def = _.get(nodeInfo, "def") || _.get(nodeInfo, "ele_style");   // 基础组件是 def 云端组件是 ele_style
  let vars = _.get(nodeInfo, "vars");
  let allVars = _.get(item, "vars");

  let map = {};
  if (vars && vars.length) {
    for (let i = 0; i < vars.length; i++) {
      let iVar = _.get(vars, `[${i}]`);
      let prop = _.get(iVar, "prop");
      let newPropName = getPropName(prop, allVars);

      iVar['prop'] = newPropName;

      if (prop !== newPropName) {
        map[prop] = newPropName;
      }
    }
  }

  if (!_.isEmpty(map)) {
    changeValName(def, map);
  }

  return nodeInfo;
}

export const getUniqNewPropName = (def) => {
  let code = $utils.getNanoid(4);

  if (def[code]) return getUniqNewPropName(def);
  return code;
}

export const initNodeDefSort = (def) => {
  if (!def._sort) def._sort = []

  for (let prop in def) {
    if (!_.startsWith(prop, "_") && _.indexOf(def._sort, prop) < 0) {
      def._sort.push(prop);
    }
  }
  return def;
}

export const addChildNodeByType = (type, parentDef, currentItem, childExtParam = {}) => {
  if(!parentDef) return;

  const name = getUniqNewPropName(parentDef)
  const newInfo = getNodeCompDefInfo(type, currentItem)
  const info = _.get(newInfo, 'def') || _.get(newInfo, 'ele_style') || {} // 基础组件是 def 云端组件是 ele_style
  const vars = _.get(newInfo, 'vars')
  const _code = $utils.getNanoid(10)

  currentItem.vars = (currentItem.vars || []).concat(vars)

  Object.assign(info, childExtParam)
  info._code = _code

  initNodeDefSort(parentDef);

  parentDef._sort.push(name)
  parentDef[name] = info

  $bus.emit('design:changeElemNodes')

  return info;
}

export default {
  isTypeEle,
  _getAlias,
  _dragClone,
  clearDefaultStyle,
  clearDefaultLowUnit,
  clearDefaultRespUnit,
  clearDefaultAnimeUnit,
  getNodeType,
  getNodeTypeIcon,
  getNodeTypeLabel,
  isMultipleNode,
  isDataNode,
  isModelNode,
  isLeafNode,
  isMicroComp,

  getItemRootByNode,
  resetCode,

  getLowPlain,
  getRespPlain,
  getAnimePlain,

  getNodeCompTpl,
  getNodeCompDefInfo,

  getUniqNewPropName,

  addChildNodeByType
}
